
/*!
 * \file     squarecontainer.cpp
 * \brief    SquareContainer implementation.
 * \author   Duriez Franck
 * \author   Carton Paul-Henri
 * \version  0.1
 */

#include "assert_macros.h"
#include <math.h>
#include "squarecontainer.h"

SquareContainer::SquareContainer(QSFMLWidget *displayWidget, QObject *parent, float *dt, Vector2i size) : /*{{{*/
	Drawable(displayWidget,parent,dt),
	Container<Square,Vector2i>(size.x * size.y),
	m_size(size),
	m_center(Vector2f(0.f,0.f)),
	m_position(Vector2f(0.f,0.f)),
	m_angle(0.f)
{
} /*}}}*/

SquareContainer::~SquareContainer() /*{{{*/
{
} /*}}}*/

/************
 * DRAWABLE *
 ************/

void SquareContainer::setCenter(Vector2f center) /*{{{*/
{
	m_center = center;
} /*}}}*/

void SquareContainer::setPosition(Vector2f position) /*{{{*/
{
	m_position = position;
} /*}}}*/

void SquareContainer::setRotation(float angle) /*{{{*/
{
	if (angle >= 0) m_angle = fmod(angle, 360.f);
	else m_angle = 360.f - fmod(-angle, 360.f);
} /*}}}*/

void SquareContainer::moveCenter(Vector2f dcenter) /*{{{*/
{
	m_center += dcenter;
} /*}}}*/

void SquareContainer::move(Vector2f dposition) /*{{{*/
{
	m_position += dposition;
} /*}}}*/

void SquareContainer::rotate(float dangle) /*{{{*/
{
	setRotation(m_angle + dangle);
} /*}}}*/

Vector2f SquareContainer::getCenter() const /*{{{*/
{
	return m_center;
} /*}}}*/

Vector2f SquareContainer::getPosition() const /*{{{*/
{
	return m_position;
} /*}}}*/

float SquareContainer::getRotation() const /*{{{*/
{
	return m_angle;
} /*}}}*/

/*************
 * CONTAINER *
 *************/

Square* SquareContainer::getObject(Vector2i coord) const throw() /*{{{*/
{
	return m_objects.at(coord.y * m_size.x + coord.x);
} /*}}}*/

void SquareContainer::setObject(Vector2i coord, Square *asquare) throw(TetrisException::UnexpectedSquare) /*{{{*/
{
	#ifdef DEBUG
	    QString deb;
	    deb += "already a square at (";
	    deb += coord.x; deb += ",";
	    deb += coord.y; deb += ")";
	#endif
	ASSERT(!getObject(coord),"", deb);

	if (getObject(coord)) throw(TetrisException::UnexpectedSquare("Impossible to set a Square, there is already one !"));

	m_objects[coord.y * m_size.x + coord.x] = asquare;

	// if asquare is not NULL
	if (asquare)
	{
		// if the square was in an other Container
		if (!(this == asquare->getContainer()))
		{
			// if it had a Container
			if (asquare->getContainer()) /*{{{*/
			{
				// we disconnect the previous Container and the Square
				// and clean it's place in this one.
				QObject::disconnect(asquare, SIGNAL(isDead(Vector2i)),
				                    asquare->getContainer(), SLOT(declareDeadObject(Vector2i)));
				int previous_place = asquare->getPositionInContainer().y *
				                     asquare->getContainer()->m_size.x +
				                     asquare->getPositionInContainer().x;
				asquare->getContainer()->m_objects[previous_place] = (Square*) NULL;
			} /*}}}*/

			// we connect the square to its new Container
			QObject::connect(asquare, SIGNAL(isDead(Vector2i)),
			                 this, SLOT(declareDeadObject(Vector2i)));

			// and we change it
			asquare->setContainer(this);
			asquare->setParent(this);
		}
		// change the position in container
		asquare->setPositionInContainer(coord);

		// format the square
		format(coord);
	}
} /*}}}*/

void SquareContainer::swap(Vector2i coord1, Vector2i coord2) throw() /*{{{*/
{
	Square* tmp = m_objects.at(coord1.y * m_size.x + coord1.x);
	m_objects[coord1.y * m_size.x + coord1.x] = m_objects.at(coord2.y * m_size.x + coord2.x);
	m_objects[coord2.y * m_size.x + coord2.x] = tmp;
	if (getObject(coord1)) getObject(coord1)->setPositionInContainer(coord1);
	if (getObject(coord2)) getObject(coord2)->setPositionInContainer(coord2);
} /*}}}*/

bool SquareContainer::isValidCoord(Vector2i coord) const throw() /*{{{*/
{
	bool res = true;
	res = res && (coord.x >= 0) && (coord.y >= 0) && (coord.x < m_size.x) && (coord.y < m_size.y);
	return res;
} /*}}}*/

